package com.ruoyi.binding.domain.JDP.Tools;

import com.alibaba.fastjson2.JSONObject;
import lombok.Setter;
import okhttp3.*;
import org.springframework.stereotype.Component;

import javax.validation.constraints.NotNull;
import java.io.IOException;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.function.Supplier;

@Component
public class OkHttpSessionClient {

    private final OkHttpClient client;

    /**
     * 多用户 Cookie 存储结构：
     * 用户名 -> host -> Cookie 列表
     */
    private final Map<String, Map<String, List<Cookie>>> userCookieStore = new ConcurrentHashMap<>();

    // 当前上下文使用的用户名（调用时要先设置）
    private final ThreadLocal<HttpInfo> currentUser = new ThreadLocal<>();


    @Setter
    private Runnable reloginCallback;

    public OkHttpSessionClient() {
        client = new OkHttpClient.Builder()
                .cookieJar(new CookieJar() {
                    @Override
                    public void saveFromResponse(@NotNull HttpUrl url, @NotNull List<Cookie> cookies) {
                        String user = currentUser.get().getDeptId();
                        if (user == null) return;

                        userCookieStore
                                .computeIfAbsent(user, k -> new ConcurrentHashMap<>())
                                .put(url.host(), cookies);
                    }

                    @org.jetbrains.annotations.NotNull
                    @NotNull
                    @Override
                    public List<Cookie> loadForRequest(@NotNull HttpUrl url) {
                        String user = currentUser.get().getDeptId();
                        if (user == null) return new ArrayList<>();

                        return userCookieStore
                                .getOrDefault(user, new HashMap<>())
                                .getOrDefault(url.host(), new ArrayList<>());
                    }
                })
                .build();
    }

    /**
     * 在每次请求前调用，设置当前操作的用户
     */
    public void setCurrentUser(String username, String baseUrl) {
        HttpInfo httpInfo = new HttpInfo();
        httpInfo.setDeptId( username);
        httpInfo.setBaseUrl(baseUrl);
        currentUser.set(httpInfo);
    }

    public HttpInfo getCurrentUser() {
        return currentUser.get();
    }

    /**
     * 重置当前上下文用户
     */
    public void clearCurrentUser() {
        currentUser.remove();
    }

    /**
     * 执行请求（带登录状态检测 + 重试）
     */
    private Response executeWithRetry(Supplier<Response> requestSupplier) throws IOException {
        Response response = requestSupplier.get();
        String body = null;
        if (response.body() != null) {
            body = response.body().string();
        }

        if (isLoginExpired(body)) {
            if (reloginCallback != null) {
                reloginCallback.run(); // 重新登录
                response = requestSupplier.get(); // 重试请求
            }
        } else {
            response = rebuildResponse(response, body);
        }

        return response;
    }

    private boolean isLoginExpired(String responseBody) {
        return responseBody.contains("未登录")
                || responseBody.contains("请先登录")
                || responseBody.contains("登录超时")
                || responseBody.contains("重新登录")
                || responseBody.contains("会话已失效");
    }

    private Response rebuildResponse(Response original, String bodyString) {
        if (original.body() != null) {
            return original.newBuilder()
                    .body(ResponseBody.create(original.body().contentType(), bodyString))
                    .build();
        }
        return original;
    }

    // ======= 通用请求方法 =======

    public Response postForm(String url, Map<String, String> formData) throws IOException {
        return executeWithRetry(() -> {
            FormBody.Builder formBuilder = new FormBody.Builder();
            formData.forEach(formBuilder::add);

            Request request = new Request.Builder()
                    .url(url)
                    .post(formBuilder.build())
                    .header("User-Agent", "Mozilla/5.0")
                    .build();

            try {
                return client.newCall(request).execute();
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        });
    }

    public Response postJson(String url, JSONObject json) throws IOException {
        return executeWithRetry(() -> {
            RequestBody body = RequestBody.create(
                    MediaType.parse("application/json; charset=utf-8"),
                    json.toJSONString()
            );

            Request request = new Request.Builder()
                    .url(url)
                    .post(body)
                    .header("User-Agent", "Mozilla/5.0")
                    .build();

            try {
                return client.newCall(request).execute();
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        });
    }

    public Response get(String url, Map<String, String> queryParams) throws IOException {
        return executeWithRetry(() -> {
            HttpUrl.Builder urlBuilder = Objects.requireNonNull(HttpUrl.parse(url)).newBuilder();
            if (queryParams != null) {
                queryParams.forEach(urlBuilder::addQueryParameter);
            }

            Request request = new Request.Builder()
                    .url(urlBuilder.build())
                    .get()
                    .header("User-Agent", "Mozilla/5.0")
                    .build();

            try {
                return client.newCall(request).execute();
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        });
    }

    /**
     * 获取当前用户的指定 Cookie
     */
    public String getCookieValue(String username, String domain, String name) {
        List<Cookie> cookies = userCookieStore
                .getOrDefault(username, Collections.emptyMap())
                .getOrDefault(domain, Collections.emptyList());

        for (Cookie cookie : cookies) {
            if (cookie.name().equals(name)) {
                return cookie.value();
            }
        }
        return null;
    }

    /**
     * 发普通 HTTP 请求（不带 Cookie / 不检查登录）
     */
    public Response simplePostJson(String url, JSONObject json) throws IOException {
        OkHttpClient simpleClient = new OkHttpClient(); // 不带 Cookie
        RequestBody body = RequestBody.create(
                MediaType.parse("application/json; charset=utf-8"),
                json.toJSONString()
        );

        Request request = new Request.Builder()
                .url(url)
                .post(body)
                .header("User-Agent", "Mozilla/5.0")
                .build();

        return simpleClient.newCall(request).execute();
    }

    public Response simpleGet(String url, Map<String, String> queryParams) throws IOException {
        OkHttpClient simpleClient = new OkHttpClient(); // 不带 Cookie
        HttpUrl.Builder urlBuilder = Objects.requireNonNull(HttpUrl.parse(url)).newBuilder();
        if (queryParams != null) {
            queryParams.forEach(urlBuilder::addQueryParameter);
        }

        Request request = new Request.Builder()
                .url(urlBuilder.build())
                .get()
                .header("User-Agent", "Mozilla/5.0")
                .build();

        return simpleClient.newCall(request).execute();
    }

}
